Skip to content

Comments

Add LoRA support in cloud relay mode#442

Merged
mjh1 merged 16 commits intomainfrom
feat-clora-test
Feb 23, 2026
Merged

Add LoRA support in cloud relay mode#442
mjh1 merged 16 commits intomainfrom
feat-clora-test

Conversation

@mjh1
Copy link
Contributor

@mjh1 mjh1 commented Feb 11, 2026

Enable LoRA browsing, selection, and install-by-URL in both cloud and local modes. Previously the LoRA UI was completely hidden in cloud mode and the backend had no cloud proxy for the LoRA list endpoint.

Backend: add cloud proxy to GET /api/v1/lora, add POST /api/v1/lora endpoint with filename inference, extension validation, and duplicate detection. Add 5-min timeout for LoRA installs in fal_app.py.

Frontend: remove isCloudMode gates in SettingsPanel and ComplexFields, switch LoRAManager to useApi hook for cloud-aware routing, add installLoRAFile to api/cloudAdapter/useApi, add install URL input UI.

emranemran and others added 3 commits February 11, 2026 00:31
Enable LoRA browsing, selection, and download-by-URL in both relay and
direct cloud modes. Previously the LoRA UI was completely hidden in cloud
mode and the backend had no cloud proxy for the LoRA list endpoint.

Backend: add cloud proxy to GET /api/v1/lora/list, add POST
/api/v1/lora/download endpoint with filename inference, extension
validation, and duplicate detection. Add 5-min timeout for LoRA
downloads in fal_app.py.

Frontend: remove isCloudMode gates in SettingsPanel and ComplexFields,
switch LoRAManager to useApi hook for cloud-aware routing, add
downloadLoRAFile to api/cloudAdapter/useApi, add download URL input UI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: emranemran <emran.mah@gmail.com>
LoRAManager: use useCloudStatus hook to disable download input/button
while cloud is connecting, show inline "Waiting for cloud connection..."
message. Use sonner toast.promise() for download progress feedback.

Backend: add response status checks in cloud proxy paths for /lora/list
and /lora/download to properly surface errors instead of crashing on
empty response data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: emranemran <emran.mah@gmail.com>
Signed-off-by: Max Holland <max@livepeer.org>
mjh1 added 2 commits February 17, 2026 10:47
Signed-off-by: Max Holland <max@livepeer.org>
Signed-off-by: Max Holland <max@livepeer.org>
@mjh1 mjh1 requested review from leszko and yondonfu February 17, 2026 11:47
@mjh1
Copy link
Contributor Author

mjh1 commented Feb 17, 2026

@yondonfu @leszko question about the UI for this, currently it's just a little input box in the settings panel:
Screenshot 2026-02-17 at 11 47 40

Should we make it like the plugins install UI instead, so another tab in the settings dialog?
Screenshot 2026-02-17 at 11 50 07

@mjh1 mjh1 marked this pull request as ready for review February 17, 2026 11:50
@leszko
Copy link
Collaborator

leszko commented Feb 17, 2026

@yondonfu @leszko question about the UI for this, currently it's just a little input box in the settings panel: Screenshot 2026-02-17 at 11 47 40

Should we make it like the plugins install UI instead, so another tab in the settings dialog? Screenshot 2026-02-17 at 11 50 07

IMO yes, installing LoRAs should be from the Settings. But happy to hear @yondonfu and @ryanontheinside thoughts.

Copy link
Collaborator

@leszko leszko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Just 2 questions:

  1. Don't you want to move this Download into the Settings?
  2. How do you clean up it for the Cloud usage? I mean so that one user would not see loras from another user? Or you just use the ephemeral container storage?

Comment on lines 139 to 155
try {
const installPromise = installLoRAFile({ url });
toast.promise(installPromise, {
loading: `Installing ${filename}...`,
success: response => response.message,
error: err => err.message || "Install failed",
});
await installPromise;
setInstallUrl("");
await loadAvailableLoRAs();
} catch (error) {
setInstallError(
error instanceof Error ? error.message : "Install failed"
);
} finally {
setIsInstalling(false);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think you'll display the toast with error twice here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7600272

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loadAvailableLoRAs should be here in the dependency array.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this has moved but it's fixed now 👍

Copy link
Contributor

@yondonfu yondonfu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to support CivitAI right now. Using the download URL for https://civitai.com/models/2383884?modelVersionId=2680702 results in an error about an invalid file extension.

Since the current LoRA user guide calls out that LoRAs can be sourced from HuggingFace and CivitAI and given that the latter is popular for LoRAs, I think we should make sure that is supported before introducing the LoRA download feature.

The linked LoRA guide contains guidance on how to programatically get the LoRA from CivitAI which might be a useful reference here. It will require a CivitAI API key which can be configured in the API Keys tab and the existing API key handling code might be specific to HuggingFace so it would just need to be tweaked a bit to handle CivitAI API keys too

async def list_api_keys():
.

@yondonfu
Copy link
Contributor

@mjh1

Should we make it like the plugins install UI instead, so another tab in the settings dialog?

I like this idea!

mjh1 added 2 commits February 19, 2026 11:44
Signed-off-by: Max Holland <max@livepeer.org>
Signed-off-by: Max Holland <max@livepeer.org>
Signed-off-by: Max Holland <max@livepeer.org>
@mjh1
Copy link
Contributor Author

mjh1 commented Feb 19, 2026

@yondonfu @leszko maybe we can avoid the complication of maintaining civitai API keys and just prompt the user to add a token queryparam? I've implemented it like that for now, see what you think 🙏 (the file extension issue is fixed now)

@mjh1
Copy link
Contributor Author

mjh1 commented Feb 19, 2026

Looks good. Just 2 questions:

  1. Don't you want to move this Download into the Settings?
  2. How do you clean up it for the Cloud usage? I mean so that one user would not see loras from another user? Or you just use the ephemeral container storage?

@leszko The settings tab is implemented now 👍
Screenshot 2026-02-19 at 12 40 27

And yes it just uses ephemeral storage which is cleaned up after every connection

@mjh1 mjh1 requested a review from yondonfu February 19, 2026 12:41
Signed-off-by: Max Holland <max@livepeer.org>
mjh1 added 4 commits February 19, 2026 15:30
Signed-off-by: Max Holland <max@livepeer.org>
Signed-off-by: Max Holland <max@livepeer.org>
Signed-off-by: Max Holland <max@livepeer.org>
Signed-off-by: Max Holland <max@livepeer.org>
mjh1 added 2 commits February 23, 2026 12:24
Signed-off-by: Max Holland <max@livepeer.org>
Signed-off-by: Max Holland <max@livepeer.org>
@mjh1 mjh1 merged commit ce98b6a into main Feb 23, 2026
6 checks passed
@mjh1 mjh1 deleted the feat-clora-test branch February 23, 2026 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants